package com.xlh.service.conclude.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.xlh.common.ResultEnum;
import com.xlh.constant.ConcludeContant;
import com.xlh.dao.conclude.ext.ConcludeCourseMapperExt;
import com.xlh.dao.conclude.ext.ConcludeMapperExt;
import com.xlh.dao.conclude.ext.ConcludeScoreMapperExt;
import com.xlh.dao.conclude.helper.*;
import com.xlh.dto.conclude.ConcludeCourseDTO;
import com.xlh.exception.common.GlobalException;
import com.xlh.param.conclude.ConcludeCourseAddParam;
import com.xlh.param.conclude.CourseWeightParam;
import com.xlh.param.conclude.SettingCourseParam;
import com.xlh.pojo.conclude.*;
import com.xlh.service.conclude.ConcludeCourseService;
import com.xlh.util.BeanUtil;
import com.xlh.vo.conclude.CourseListInfoVO;
import com.xlh.vo.conclude.CourseListStudentInfoVO;
import com.xlh.vo.conclude.CourseWeightVO;
import com.xlh.vo.conclude.SettingCourseVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class ConcludeCourseServiceImpl implements ConcludeCourseService {


    @Autowired
    private ConcludeCourseMapperHelper concludeCourseMapperHelper;

    @Autowired
    private ConcludeCourseMapperExt concludeCourseMapperExt;

    @Autowired
    private ConcludeSubCourseMapperHelper concludeSubCourseMapperHelper;

    @Autowired
    private ConcludeMapperHelper concludeMapperHelper;

    @Autowired
    private ConcludeCheckSubMapperHelper concludeCheckSubMapperHelper;

    @Autowired
    private ConcludeCheckMapperHelper concludeCheckMapperHelper;



    @Override
    public List<CourseListInfoVO> list(Long concludeId) {

        if(ObjectUtil.isNull(concludeId)){
            throw new GlobalException(ResultEnum.BAD_REQUEST);
        }
        List<ConcludeCourse> concludeCourses = concludeCourseMapperHelper.findByCondition(concludeId);
        List<CourseListInfoVO> courseListInfoVOS = BeanUtil.batchTransform(CourseListInfoVO.class, concludeCourses);

        String chacheKey = concludeCourses.stream().map(concludeCourse -> String.valueOf(concludeCourse.getId())).collect(Collectors.joining());
        List<String> chacheResult = (List<String>)ConcludeScoreServiceImpl.timeChache.get(chacheKey);

        if(CollectionUtil.isNotEmpty(chacheResult)){
            chacheResult = chacheResult.subList(3, chacheResult.size());
            ConcludeScoreServiceImpl.timeChache.remove(chacheKey);
        }
        Conclude conclude = concludeMapperHelper.get(concludeId);
        if(ObjectUtil.isNull(conclude)){
            throw new GlobalException(ResultEnum.NOT_FOUND_CONCLUDE);
        }
        BigDecimal thresholdValue = NumberUtil.div(conclude.getThresholdValue(), 100d);// 阈值
        int index = 0;
        for (CourseListInfoVO courseListInfoVO : courseListInfoVOS) {

            if(CollectionUtil.isEmpty(chacheResult)){

                courseListInfoVO.setExpectSocre(null);
                courseListInfoVO.setScore(null);
                courseListInfoVO.setIsReach(false);
            }else{
                courseListInfoVO.setExpectSocre(getExpectSocre(chacheResult, index, thresholdValue));
                index++;   // 指针向后移动
                courseListInfoVO.setScore(getSocre(chacheResult, index));
                courseListInfoVO.setIsReach(false);
                if(ObjectUtil.isNotNull(courseListInfoVO.getScore()) && ObjectUtil.isNotNull(courseListInfoVO.getExpectSocre()) ){
                    int compare = NumberUtil.compare(courseListInfoVO.getScore(), courseListInfoVO.getExpectSocre());
                    courseListInfoVO.setIsReach(compare >= 0);
                }
                index++;
            }
        }
        return courseListInfoVOS;
    }

    /**
     * 获取学生真实得分
     * @param chacheResult
     * @param index
     * @return
     */
    private Double getSocre(List<String> chacheResult, int index) {

        if(CollectionUtil.isEmpty(chacheResult)){
            return null;
        }
        String score = chacheResult.get(index);
        if(StrUtil.isBlank(score)){
            return null;
        }
        return Double.valueOf(score);
    }

    /**
     * 获取期望分值
     * @param chacheResult
     * @param index
     * @param thresholdValue
     * @return
     */
    private Double getExpectSocre(List<String> chacheResult,
                                  int index, BigDecimal thresholdValue) {

        if(CollectionUtil.isEmpty(chacheResult)){
            return null;
        }
        String expectSocre = chacheResult.get(index);
        if(StrUtil.isBlank(expectSocre)){
            return null;
        }
        BigDecimal bigDScore = new BigDecimal(expectSocre);
        BigDecimal mul = NumberUtil.mul(bigDScore, thresholdValue);

        return mul.doubleValue();
    }


    @Override
    public void add(List<ConcludeCourseAddParam> concludeCourseAddParams) {

        List<ConcludeCourseDTO> dtos = BeanUtil.batchTransform(ConcludeCourseDTO.class, concludeCourseAddParams);
        if(CollectionUtil.isEmpty(concludeCourseAddParams)){
            throw new GlobalException(ResultEnum.NOT_FOUND_CONCLUDE);
        }
        Long concludeId = dtos.get(0).getConcludeId();
        // 原来记录
        List<ConcludeCourse> quondamRecords = concludeCourseMapperHelper.findByCondition(concludeId);

        // 设置Order值
        settingOrder(dtos);
        // 根据ID决定更新或者是插入
        Map<Boolean, List<ConcludeCourseDTO>> insertOrUpdateRecord = dtos.stream().collect(Collectors.partitioningBy(dto -> Objects.isNull(dto.getId())));
        // 插入记录
        List<ConcludeCourse> insertRecord = BeanUtil.batchTransform( ConcludeCourse.class, insertOrUpdateRecord.get(true)) ;
        // 更新记录
        List<ConcludeCourse> updateRecord = BeanUtil.batchTransform( ConcludeCourse.class, insertOrUpdateRecord.get(false));

        List<Long> updateRecordId = updateRecord.stream().map(ConcludeCourse::getId).collect(Collectors.toList());
        // 对比获取删除记录
        List<ConcludeCourse> deleteRecord = quondamRecords.stream()
                    .filter(quondamRecord -> !updateRecordId.contains(quondamRecord.getId()))
                    .collect(Collectors.toList());

        List<Long> prepareDelCourseIds = deleteRecord.stream().map(ConcludeCourse::getId).collect(Collectors.toList());
        // 删除课程表记录
        if(CollectionUtil.isNotEmpty(prepareDelCourseIds)){
            concludeCourseMapperHelper.batchDeleted( prepareDelCourseIds );
        }
        // 删除已有的关联项
        if(CollectionUtil.isNotEmpty(prepareDelCourseIds)){
            concludeSubCourseMapperHelper.deleteByCourseId(prepareDelCourseIds);
        }
        // 更新记录
        if(CollectionUtil.isNotEmpty(updateRecord)){
            concludeCourseMapperHelper.batchUpdate(updateRecord);
        }
        // 执行插入记录
        if(CollectionUtil.isNotEmpty(insertRecord)){
            concludeCourseMapperExt.insertBatch(insertRecord);
        }
    }

    @Override
    public List<CourseListStudentInfoVO> listStudent(Long courseId) {

        // 1. 根据course查询正在
        Conclude concludeIsPublic = concludeMapperHelper.getConcludeIsPublic(courseId);
        List<CourseListStudentInfoVO> result = Lists.newArrayList();

        // 1. 查询目标信息
        if(ObjectUtil.isNotNull(concludeIsPublic)){
            Long concludeId = concludeIsPublic.getId();
            List<CourseListInfoVO> list = Lists.newArrayList();
            Conclude conclude = concludeMapperHelper.get(concludeId);
            if(conclude.getIsPublish()){
                List<ConcludeCourse> concludeCourses = concludeCourseMapperHelper.findByCondition(concludeId);
                list = BeanUtil.batchTransform(CourseListInfoVO.class, concludeCourses);
            }
            if(CollectionUtil.isNotEmpty(list)){
                for (int i = 0; i < list.size(); i++) {
                    CourseListInfoVO courseListInfoVO = list.get(i);
                    DecimalFormat myFormat = new DecimalFormat("00");
                    String courseName = ConcludeContant.HEAR_OTHER + myFormat.format(i+1);
                    CourseListStudentInfoVO courseInfoVo = new CourseListStudentInfoVO();
                    courseInfoVo.setDetails(courseListInfoVO.getDetails());
                    courseInfoVo.setCourseName(courseName);
                    result.add(courseInfoVo);
                }
            }
        }
        return result;
    }

    @Override
    public void settingWeight(SettingCourseParam settingCourseParam) {

        List<CourseWeightParam> countCourseParams = Lists.newArrayList();
        // 1. 检查设置的权重值和是否是100
        List<CourseWeightParam> courseParams = settingCourseParam.getCourseParams().stream().filter(courseParam -> ObjectUtil.isNotNull(courseParam.getWeight())).collect(Collectors.toList());
        Long subId = settingCourseParam.getSubId();

        if(CollectionUtil.isNotEmpty(courseParams)){

            countCourseParams.addAll(courseParams);
            Long sum = countCourseParams.stream().mapToLong(CourseWeightParam::getWeight).sum();
            if(sum != 100L){
                throw new GlobalException(ResultEnum.NOT_FULL_WEIGHT);
            }
        }
        // 2. 删除原有subId关联的课程
        concludeSubCourseMapperHelper.deleteBySubId(Lists.newArrayList(subId));
        List<ConcludeSubCourse> concludeSubCourses = Lists.newArrayList();
        for (CourseWeightParam courseParam : courseParams) {

            if(ObjectUtil.isNotNull(courseParam.getWeight())){
                ConcludeSubCourse concludeSubCourse = new ConcludeSubCourse();
                concludeSubCourse.setCheckSubId(subId);
                concludeSubCourse.setConCourseId(courseParam.getCourseId());
                concludeSubCourse.setCourseWeight(courseParam.getWeight());
                concludeSubCourses.add(concludeSubCourse);
            }
        }

        if(CollectionUtil.isNotEmpty(concludeSubCourses)){
            concludeSubCourseMapperHelper.insertBatch(concludeSubCourses);
        }

    }

    @Override
    public SettingCourseVO getCourseWeight(Long subId) {

        if(ObjectUtil.isNull(subId)){
            throw new GlobalException(ResultEnum.BAD_REQUEST);
        }
        // 1. 查询所有课程权重值
        ConcludeCheckSub concludeCheckSub = concludeCheckSubMapperHelper.get(subId);
        ConcludeCheck checkRecord = concludeCheckMapperHelper.getById(concludeCheckSub.getCheckId());
        Long concludeId = checkRecord.getConcludeId();

        List<ConcludeCourse> allCourse = concludeCourseMapperHelper.findByCondition(concludeId);
        List<ConcludeSubCourse> subCourses = concludeSubCourseMapperHelper.findBySubId(subId);

        SettingCourseVO settingCourseVO = new SettingCourseVO();
        settingCourseVO.setSubId(subId);
        List<CourseWeightVO> linkedRecord = Lists.newArrayList();
        settingCourseVO.setCourseParams(linkedRecord);

        for (ConcludeCourse concludeCourse : allCourse) {

            Long courseId = concludeCourse.getId();
            CourseWeightVO courseWeightVO = new CourseWeightVO();
            courseWeightVO.setCourseId(concludeCourse.getId());
            for (ConcludeSubCourse subCours : subCourses) {
                Long conCourseId = subCours.getConCourseId();
                if(courseId.equals(conCourseId)){
                    courseWeightVO.setWeight(subCours.getCourseWeight());
                }
            }
            linkedRecord.add(courseWeightVO);
        }

        return settingCourseVO;
    }

    /**
     * 设置order的值
     * @param dtos
     */
    private void settingOrder(List<ConcludeCourseDTO> dtos) {

        for (int i = 0; i < dtos.size(); i++) {
            dtos.get(i).setOrder(i+1);
        }
    }

    /**
     * 校验当前dto参数是否正确
     * @param dtos
     */
    private void checkDto(List<ConcludeCourseDTO> dtos) {

        boolean isHaveWeight = dtos.stream().anyMatch(dto -> ObjectUtil.isNotNull(dto.getWeight()));

        if(isHaveWeight){

            List<ConcludeCourseDTO> collect = dtos.stream().filter(concludeCourseDTO -> ObjectUtil.isNotNull(concludeCourseDTO.getWeight())).collect(Collectors.toList());
            double sumWeight = collect.stream().mapToDouble(ConcludeCourseDTO::getWeight).sum();
            if(!ConcludeCourse.FULL_WEIGHT.equals(sumWeight)){
                throw new GlobalException(ResultEnum.NOT_FULL_WEIGHT);
            }
        }


    }


}
